#include "Precomp.h"
#include "AllBindings.h"
#include <fastsig/fastsig.hpp>
#include <boost/bind.hpp>

//event system for Squirrel

struct sqDelegate: public fastsig::trackable
{
	SquirrelObject target;
	sqDelegate(SquirrelObject& target)
		:target(target){}
	void operator()(SquirrelObject& param)
	{
		SquirrelVM::BeginCall(target);
		SquirrelVM::PushObject(param);
		SquirrelVM::EndCall();
	}
};

class sqConnection : public fastsig::connection
{
public:
	sqConnection(){}
	sqConnection(const fastsig::connection& con,sqDelegate* delegate)
		:fastsig::connection(con),delegate(delegate)
	{
	}
	~sqConnection()
	{
		delete delegate;
	}
private:
	sqDelegate* delegate;
};

DECLARE_INSTANCE_TYPE_NAME(sqConnection,Connection);

class Signal: public fastsig::signal<void(SquirrelObject&)>
{
public:
	int add(HSQUIRRELVM vm)
	{
		StackHandler s(vm);
		SquirrelObject slot=s.GetObjectHandle(2);//get the function
		//create a delegate
		sqDelegate* delegate=new sqDelegate(slot);
		Push(vm,sqConnection(connect(*delegate,*delegate),delegate));
		return 1;
	}
	int call(HSQUIRRELVM vm)
	{
		StackHandler s(vm);
		SquirrelObject arg=s.GetObjectHandle(2);
		(*this)(arg);
		return SQ_OK;
	}
};

DECLARE_INSTANCE_TYPE_NOCOPY(Signal);

void bindAddOn()
{
	SQClassDef<Signal>(L"Signal")
		.funcVarArgs(&Signal::add,L"connect",L"t|c")
		.funcVarArgs(&Signal::call,L"_call",L".");
	SQClassDef<sqConnection>(L"Connection");
}